package com.fwmagic.akka.rpc

import akka.actor.{Actor, ActorSelection, ActorSystem, Props}
import com.typesafe.config.{Config, ConfigFactory}
import java.util.UUID
import java.util.concurrent.TimeUnit
import scala.concurrent.duration.FiniteDuration

/**
  * 向Master注册，接收消息，并定时发送心跳报活
  */
class Worker extends Actor {

    //定义WorkerId
    val workerId = "worker-" + UUID.randomUUID().toString

    //master的引用
    var masterRef: ActorSelection = _

    /**
      * 生命周期方法
      * 在构造方法之后，receive方法之前，执行一次preStart
      */
    override def preStart(): Unit = {
        //获取Master的引用
        masterRef = context.actorSelection("akka.tcp://Master-Actor-System@localhost:8888/user/Master-Actor")

        //Worker向Master注册
        masterRef ! RegisterWorker(workerId, 2048, 4)
    }

    /**
      * 接收消息
      *
      * @return
      */
    override def receive: Receive = {
        //已注册：Master反馈给Worker的注册成功消息
        case RegistedWorker => {
            //1、向Master报活前，先向自己报活
            import context.dispatcher
            context.system.scheduler.schedule(new FiniteDuration(0, TimeUnit.SECONDS), new FiniteDuration(5, TimeUnit.SECONDS), self, SendHeartBeat)
        }

        //2、然后定时向Master报活
        case SendHeartBeat => {
            //做一些对master的检测等操作 TODO

            //向Master报活，指定workerId
            masterRef ! HeartBeat(workerId)

            println(System.currentTimeMillis() + " ===>worker发送心跳给master")
        }

    }
}

/**
  * 创建workerActorSystem和workActor
  */
object Worker {
    def main(args: Array[String]): Unit = {
        val host = "localhost"
        val port = "9998"

        val confStr =
            s"""
               |akka.actor.provider="akka.remote.RemoteActorRefProvider"
               |akka.remote.netty.tcp.hostname=$host
               |akka.remote.netty.tcp.port=$port
            """.stripMargin

        val config: Config = ConfigFactory.parseString(confStr)

        val workerActorSystem: ActorSystem = ActorSystem("Worker-Actor-System", config)

        //val workActor: ActorRef = workerActorSystem.actorOf(Props[Worker], "Worker-Actor")
        workerActorSystem.actorOf(Props[Worker], "Worker-Actor")

    }
}